/**
 * 
 */
package edu.vanderbilt.vshare.multicast;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

/**
 * thread for listening to a multicast address for file packets
 * 
 * @author jedmondson
 *
 */
public class MulticastListenerThread implements Runnable {

	/**
	 * Constructor for a listener thread
	 * 
	 * @param         ip              multicast ip address to listen on
	 * @param         port            port to bind to
	 */
	public MulticastListenerThread(String ip, int port) {
		try
		{
			socket = new MulticastSocket(port);
			socket.joinGroup(InetAddress.getByName(ip));
		}
		catch (IOException e)
		{
			failed = true;
		}
	}

	/**
	 * thread loop for reading packets from a multicast ip and port and then filling
	 * a file store with the received packets
	 */
	
	@Override
	public void run() {

		byte [] buf = new byte [16 + payloadSize];
		DataPacket packet = new DataPacket();
		DatagramPacket datagram = new DatagramPacket(buf, buf.length);
		int remainingPackets = -1;

		while (remainingPackets != 0 && !SharedGlobals.shutdown.get())
		{
			Utility.fillNulls(buf);
			datagram.setData(buf);
			try
			{
				socket.receive(datagram);
	
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
	
			boolean correct = packet.read(datagram.getData(), payloadSize);
			
			int length = datagram.getLength();
			
			if (!correct)
			{
				fileid = packet.getFileid();
				int number = packet.getNumber();
				byte [] payload = packet.getPayload();

				System.out.println ("The " + length + " length packet (" +
						fileid + ":" + number + ") had errors in transit");
				
				String string = new String (payload);
				
				string = Utility.trimZeros(string);
				
				//System.out.println ("payload would have been... " + string);
			}
			else
			{
				fileid = packet.getFileid();
				int number = packet.getNumber();
				byte [] payload = packet.getPayload();
				
				System.out.println ("File: " + fileid);
				System.out.println ("Number: " + number);
				
				if (number == -1)
				{
					if (SharedGlobals.store.contains(fileid))
					{
						System.out.println ("We already have this file.");
					}
					else
					{
						// we have new metadata
						System.out.println ("We do not have this file.");
						SharedGlobals.store.add(fileid, payload);
						
						if (!SharedGlobals.store.contains(fileid))
						{
							System.out.println ("We were unable to add the file.");
						}
					}
				} // end if number == -1
				else 
				{
					SharedGlobals.store.add(fileid, number, payload);
					
					if (SharedGlobals.store.contains(fileid))
						remainingPackets = SharedGlobals.store.remainingPackets(fileid);
					
					System.out.println ("Incompletes are now " + 
							SharedGlobals.store.remainingPackets(fileid));
				}
			} // end correct
		} // end while client is not shutdown
		
		System.out.println ("Is Complete is returning " + SharedGlobals.store.isComplete(fileid));
		socket.close();
	}

	/**
	 * @return the failed
	 */
	public boolean isFailed() {
		return failed;
	}

	/**
	 * @param failed the failed to set
	 */
	public void setFailed(boolean failed) {
		this.failed = failed;
	}

	/**
	 * @return the fileid
	 */
	public int getFileid() {
		return fileid;
	}

	/**
	 * @return the rate
	 */
	public String getRate() {
		return rate;
	}

	/**
	 * @return the payloadSize
	 */
	public int getPayloadSize() {
		return payloadSize;
	}

	/**
	 * @param payloadSize the payloadSize to set
	 */
	public void setPayloadSize(int payloadSize) {
		this.payloadSize = payloadSize;
	} 
	
	private MulticastSocket socket;
	private boolean failed = false;

	private int fileid;
	private String rate;

	private int payloadSize = 16384;
}
